#include "CameraPrecompiled.hxx"
#include "CameraArcball.hxx"

Eifersucht::Arcball::Float32x3 Eifersucht::Arcball::Convert( 
	_In_ Float32Const fXScreen, 
	_In_ Float32Const fYScreen 
	)
{
	Float32x3 f3Result(
		(fXScreen - m_i2Offset.x - m_iWindowWidth / 2) / -(m_fRadius * m_iWindowWidth / 2),
		(fYScreen - m_i2Offset.y - m_iWindowHeight / 2) / (m_fRadius * m_iWindowHeight / 2),
		0.0f // z = 0 !
		);

	Float32Const fLenSq = f3Result.Dot(f3Result);

	if ( fLenSq > 1.0f)
	{
		Float32Const fScale = 1.0f / sqrtf(fLenSq);
		f3Result *= fScale; // x and y *= scale
	}
	else
	{
		f3Result.z = sqrtf(
			1.0f - fLenSq
			);
	}

	return f3Result;
}

Eifersucht::Arcball::Arcball()
{
	Reset();
	m_f3StartPosition = DirectX::XMVectorZero();
	m_f3EndPosition = DirectX::XMVectorZero();
	m_i2Offset.x = 0i16;
	m_i2Offset.y = 0i16;

	auto WndRect = RECT();
	if (GetClientRect( GetForegroundWindow(), &WndRect ))
	{
		SetWindow( 
			_To_short WndRect.right, 
			_To_short WndRect.bottom
			);
	}
	else
	{
		PrintToDebugWindowOnly8( 
			"Arcball::Arcball: Warning: "
			"Failed to get client rect. "
			"Tip: SetWindow(w,h,r)."
			);
	}
}

void Eifersucht::Arcball::Reset() 
{
	m_bDragging = false;
	m_fRadius = ArcballDefaultRadius;
	m_fTranslationRadius = ArcballDefaultRadius;
	m_f4Now = DirectX::XMQuaternionIdentity();
	m_f4Last = DirectX::XMQuaternionIdentity();
	m_f4x4Rotation = DirectX::XMMatrixIdentity();
	m_f4x4Translation = DirectX::XMMatrixIdentity();
	m_f4x4TranslationDelta = DirectX::XMMatrixIdentity();
}

Eifersucht::Arcball::Quaternion REIGN_METHODSTDCALLTYPE Eifersucht::Arcball::QuaternionFromBallPoints(
	_In_ Float32x3ConstPtr cpf3From, 
	_In_ Float32x3ConstPtr cpf3To
	)
{
	// q=[ w v ]=[ w (x y z) ]
	// q( O,n )=[ cos(O/2) (sin(O/2))*n ]
	auto const fDot = (*cpf3From).Dot((*cpf3To));		// w
	auto const f3Cross = (*cpf3From).Cross((*cpf3To));	// x y z
	return Quaternion(f3Cross, fDot);
}

Void Eifersucht::Arcball::OnDragStart( _In_ Int16 iXPtr, _In_ Int16 iYPtr )
{
	if ((iXPtr >= m_i2Offset.x) && // Only enter the dragging the start if the pointer
        (iYPtr >= m_i2Offset.y) && // is in the drag rectangle.
        (iXPtr < m_i2Offset.x + m_iWindowWidth) &&
        (iYPtr < m_i2Offset.y + m_iWindowHeight))
	{
		//PrintToDebugWindowOnly8( "Eifersucht::Arcball: OnDragStart." );

		m_bDragging = true;
		m_f4Last = m_f4Now;

		m_f3StartPosition = Convert( // To cam arc ball space
			_To_float iXPtr, _To_float iYPtr
			);
	}
}

//Void Eifersucht::Arcball::OnDragContinue( _In_ Int16 iXPtr, _In_ Int16 iYPtr )
//{
//	if ( m_bDragging )
//	{
//		//PrintToDebugWindowOnly8( "Eifersucht::Arcball: OnDragContinue." );
//
//		m_f3EndPosition = Convert(
//			_To_float iXPtr, 
//			_To_float iYPtr
//			);
//
//		m_f4Now = m_f4Last * QuaternionFromBallPoints( 
//			(&m_f3StartPosition), 
//			(&m_f3EndPosition) 
//			);
//	}
//}

//Void Eifersucht::Arcball::OnDragStop()
//{
//	//PrintToDebugWindowOnly8( "Eifersucht::Arcball: OnDragStop." );
//	m_bDragging = false;
//}
